#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "MSTK.h"


#ifdef __cplusplus
extern "C" {
#endif

  /* 
     This function extract the three layers of mesh into a layer_mesh
  */
int MESH_Vol_CreateLayer(Mesh_ptr mesh,Mesh_ptr layer_mesh);
int MESH_Surf_CreateLayer(Mesh_ptr mesh, Mesh_ptr layer_mesh);

int MESH_CreateLayer(Mesh_ptr mesh, Mesh_ptr layer_mesh ) {
  int nf, nr;
  /* basic mesh information */
  nf = MESH_Num_Faces(mesh);
  nr = MESH_Num_Regions(mesh);
  if (nr)
    MESH_Vol_CreateLayer(mesh, layer_mesh);
  else if(nf) 
    MESH_Surf_CreateLayer(mesh, layer_mesh);
  else {
    MSTK_Report("MESH_CreateLayer()","only send volume or surface mesh",ERROR);
    exit(-1);
  }
  return 1;
}

int MESH_Surf_CreateLayer(Mesh_ptr mesh, Mesh_ptr layer_mesh) {
  int i, j, index_vertex, idx, nv, nf, nfv, nvf,natt, ncomp;
  MVertex_ptr mv,mv_new;
  MFace_ptr mf, mf_new;
  List_ptr mfverts, mvfaces;

  /* get the three layer vertex and face */
  List_ptr layer_vertex = List_New(10), layer_face = List_New(10);
  int mkvid = MSTK_GetMarker();
  int mkfid = MSTK_GetMarker();
  int *v_g2l = (int *) MSTK_malloc(MESH_Num_Vertices(mesh)*sizeof(int));

  /* get layer face, ghost faces plus utilized vertex adj faces */
  idx = 0;
  while(mf = MESH_Next_GhostFace(mesh,&idx)) {
    List_Add(layer_face,mf);
    MEnt_Mark(mf,mkfid);
  }
  idx = 0;
  while(mv = MESH_Next_UtVertex(mesh,&idx)) {
    mvfaces = MV_Faces(mv);
    nvf = List_Num_Entries(mvfaces);
    for(j = 0; j < nvf; j++) {
      mf = List_Entry(mvfaces,j);
      if ( MEnt_IsMarked(mf,mkfid) )
	continue;
      List_Add(layer_face,mf);
      MEnt_Mark(mf,mkfid);
    }
    List_Delete(mvfaces);
  }
  /* get layer vertex, from layer face */
  nf = List_Num_Entries(layer_face);
  index_vertex = 0;
  for(j = 0; j < nf; j++) {
    mf = List_Entry(layer_face,j);
    mfverts = MF_Vertices(mf,1,0);
    nfv = List_Num_Entries(mfverts);
    for(i = 0; i < nfv; i++) {
      mv = List_Entry(mfverts,i);
      if (MEnt_IsMarked(mv,mkvid))
	continue;
      List_Add(layer_vertex,mv);
      MEnt_Mark(mv,mkvid);
      v_g2l[MV_ID(mv)-1] = index_vertex++;
    }
    List_Delete(mfverts);
  }

  List_Unmark(layer_vertex,mkvid);
  List_Unmark(layer_face,mkfid);

  nv = List_Num_Entries(layer_vertex);

  /* creat this layer mesh */
  MVertex_ptr *fverts = (MVertex_ptr *) MSTK_malloc(MAXPV2*sizeof(MVertex_ptr));
  MVertex_ptr *verts = (MVertex_ptr *) MSTK_malloc(nv*sizeof(MVertex_ptr));
  for(i = 0; i < nv; i++) {
    mv = List_Entry(layer_vertex,i);
    verts[i] = MV_New(layer_mesh);
    PMV_Duplicate(mv,verts[i]);
    MV_Set_PType(verts[i],MV_PType(mv));
  }
  for(i = 0; i < nf; i++) {
    mf = List_Entry(layer_face,i);
    mf_new = MF_New(layer_mesh);
    mfverts = MF_Vertices(mf,1,0);
    nfv = List_Num_Entries(mfverts);
    for(j = 0; j < nfv; j++)
      fverts[j] = verts[v_g2l[MV_ID(List_Entry(mfverts,j))-1]];
    MF_Set_Vertices(mf_new,nfv,fverts);
    PMF_Duplicate(mf,mf_new);
    MF_Set_PType(mf_new,MF_PType(mf));
    List_Delete(mfverts);
  }

  List_Delete(layer_vertex);
  List_Delete(layer_face);
  MSTK_free(v_g2l);
  MSTK_free(fverts);

  return 1;
}


int MESH_Vol_CreateLayer(Mesh_ptr mesh, Mesh_ptr layer_mesh) {
  return 1;
}
  
#ifdef __cplusplus
}
#endif

